/*
 * Copyright © 2021 http://www.hn-szzy.com/ All rights reserved.
 */
package com.xjh.service.studyjava.testproxy.staticproxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * @author： 徐建华
 * @date： 2022/2/7
 * @description：
 */
public class JdkHandler implements InvocationHandler {

    // 目标对象，目标对象的类型不固定，创建时动态生成（不像上面直接创建一个固定的肖生客代理对象）
    private Object target;

    // 通过构造器将目标对象赋值
    public JdkHandler(Object target) {
        this.target = target;
    }

    /**
     * 1、调用目标对象的方法（返回Object）
     * 2、增强目标对象的行为
     *
     * @param proxy  调用该方法的代理实例
     * @param method 目标对象的方法
     * @param args   目标对象的方法形参
     * @return
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        // 增强行为
        System.out.println("==============方法前执行");

        // 调用目标对象的方法（返回Object）
        Object result = method.invoke(target, args);

        // 增强行为
        System.out.println("方法后执行==============");

        return result;
    }

/*​ 相比于静态代理，动态代理在创建代理对象上更加的灵活，
动态代理类的字节码在程序运行时，由Java反射机制动态产生。
它会根据需要，通过反射机制在程序运行期，动态的为目标对象创建代理对象，无需程序员手动编写它的源代码。
动态代理不仅简化了编程工作，而且提高了软件系统的可扩展性，因为反射机制可以生成任意类型的动态代理类。
代理的行为可以代理多个方法，即满足生产需要的同时又达到代码通用的目的。*/

    /**
     * 得到代理对象
     * public static Object newProxyInstance(ClassLoader loader,
     * Class<?>[] interfaces,
     * InvocationHandler h)
     * loader：类加载器，一个ClassLoader对象，定义了由哪个ClassLoader对象来对生成的代理对象进行加载
     * interfaces：一个Interface对象的数组，表示的是我将要给我需要代理的对象提供一组什么接口，如果我提供了一组接口给它，那么这个代理对象就宣称实现了该接口(多态)，这样我就能调用这组接口中的方法了
     * h：一个InvocationHandler接口，表示代理实例的调用处理程序实现的接口。每个代理实例都具有一个关联的调用处理程序。对代理实例调用方法时，将对方法调用进行编码并将其指派到它的调用处理程序            的 invoke 方法（传入InvocationHandler接口的子类）
     *
     * @return 返回一个指定接口的代理类的实例方法调用分派到指定的调用处理程序。 (返回代理对象)
     */
    public Object getProxy() {
        return Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
    }
}
